﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Media;
using Red.Controls.TimeLine.Core;

namespace Red.Controls.TimeLine.TracksTree
{
    class TimeCursor : FrameworkElement
    {
        #region Private data

        private const double _penSize = 3;
        private const double _timeTextOffset = _penSize + 3;

        private readonly static CultureInfo _fontCultureInfo = CultureInfo.GetCultureInfo( "en-us" );
        private readonly static Typeface _fontFace = new Typeface( "Verdana" );
        private readonly static double _fontSize = 12;

        private Pen _cursorPen = null;
        
        #endregion

        static TimeCursor()
        {
            DefaultStyleKeyProperty.OverrideMetadata( typeof( TimeCursor ), new FrameworkPropertyMetadata( typeof( TimeCursor ) ) );
        }

        #region Ctr

        public TimeCursor()
        {
            _cursorPen = new Pen( (Brush)FillProperty.GetMetadata( this ).DefaultValue, _penSize );

            SnapsToDevicePixels = true;
            IsHitTestVisible = false;
        }

        #endregion

        #region Dependency properties

        public double Time
        {
            get { return (double)GetValue( TimeProperty ); }
            set { SetValue( TimeProperty, value ); }
        }

        public Brush Fill   
        {
            get { return (Brush)GetValue( FillProperty ); }
            set { SetValue( FillProperty, value ); }
        }

        public Brush Foreground
        {
            get { return (Brush)GetValue( ForegroundProperty ); }
            set { SetValue( ForegroundProperty, value ); }
        }

        public static readonly DependencyProperty TimeProperty =
            DependencyProperty.Register( "Time", typeof( double ), typeof( TimeCursor ),
                new FrameworkPropertyMetadata( 0.0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender ) );

        public static readonly DependencyProperty FillProperty =
            DependencyProperty.Register( "Fill", typeof( Brush ), typeof( TimeCursor ), 
                new FrameworkPropertyMetadata( new SolidColorBrush( Colors.Pink ), FrameworkPropertyMetadataOptions.AffectsRender, 
                    new PropertyChangedCallback( OnPenChanged ) ) );

        public static readonly DependencyProperty ForegroundProperty =
         DependencyProperty.Register( "Foreground", typeof( Brush ), typeof( TimeCursor ),
            new FrameworkPropertyMetadata( new SolidColorBrush( Colors.Black ), FrameworkPropertyMetadataOptions.AffectsRender ) );

        private static void OnPenChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            TimeCursor cursor = (TimeCursor)d;
            cursor._cursorPen = new Pen( (Brush)e.NewValue, _penSize );
        }

        #endregion
     
        protected override Size MeasureOverride( Size constraint )
        {
            Size textSize = MeasureValueLabelSize( Time );

            double width = constraint.Width;
            double height = constraint.Height;

            if ( Double.IsInfinity( height ) )
            {
                return textSize;
            }

            double desiredWidth = Math.Min( _timeTextOffset + textSize.Width, width );
            Size desiredSize = new Size( desiredWidth, height );

            return desiredSize;
        }               

        protected override void OnRender( DrawingContext ctx )
        {
            double height = base.ActualHeight;

            Point top = new Point( 0, 0 );
            Point bottom = new Point( 0, height );

            ctx.DrawLine( _cursorPen, top, bottom );

            Point timePosition = new Point( _timeTextOffset, bottom.Y );
            RenderTimeValue( ctx, Time, timePosition );
        }

        private void RenderTimeValue( DrawingContext ctx, double value, Point textPosition )
        {
            string text = TimeLineControler.TimeToString( value );

            FormattedText formattedText = new FormattedText( text, _fontCultureInfo, FlowDirection.LeftToRight, _fontFace, _fontSize, Brushes.Black );
            formattedText.SetForegroundBrush( Foreground );

            textPosition.Y -= formattedText.Height;

            ctx.DrawText( formattedText, textPosition );
        }

        private Size MeasureValueLabelSize( double value )
        {
            string text = value.ToString();

            FormattedText formattedText = new FormattedText( text, _fontCultureInfo, FlowDirection.LeftToRight, _fontFace, _fontSize, Brushes.Black );
            Size size = new Size( formattedText.Width, formattedText.Height );

            return size;
        }
    }    
}